<template>
  <div
    class="finder"
    :class="isMobile() ? 'finder-mobile' : ' '"
    ref="finderRef"
    @click="hideMenu"
  >
    <el-container>
      <el-aside class="left" :class="miniLeft ? 'miniLeft' : ''" width="200px">
        <div class="disk-wrapper">
          <el-scrollbar>
            <el-tree
              accordion
              ref="treeRef"
              class="dir-tree"
              :data="dirTree"
              :props="{
                children: 'children',
                label: 'path',
              }"
              default-expand-all
              expand-on-click-node
              node-key="physicalPath"
              @node-click="handleNodeClick"
            >
              <template #default="{ node, data }">
                <div class="disk-item" :class="data.root ? 'root' : ''">
                  <div class="disk-title-wrapper">
                    <img
                      v-if="data.root"
                      :class="`disk-icon disk-icon-${data.driveType}`"
                      src=""
                      alt=""
                    />
                    <span>{{ node.label }}</span>
                    <span class="title">
                      {{ data.label }}
                    </span>
                  </div>

                  <div class="progress-wrapper" v-if="data.root">
                    <el-progress
                      :percentage="
                        ((data.totalSize - data.totalFreeSpace) * 100) / data.totalSize
                      "
                    >
                      <template #default="{ percentage }">
                        <span class="percentage-value">{{ percentage.toFixed(2) }}%</span>
                      </template>
                    </el-progress>
                  </div>
                </div>
              </template>
            </el-tree>
          </el-scrollbar>
          <div class="disk-footer">
            <el-icon v-if="miniLeft" @click="miniLeft = false"><Expand /></el-icon>
            <el-icon v-else @click="miniLeft = true"><Fold /></el-icon>
          </div>
        </div>
      </el-aside>
      <el-main class="folder-wrapper">
        <div class="tool-bar" v-if="data.fileInfos">
          <!-- <el-button-group>
            <el-button size="small" :icon="ArrowLeft">
              <el-icon class="el-icon--right"><ArrowLeft /></el-icon>
            </el-button>
            <el-button size="small" :icon="ArrowRight">
              <el-icon class="el-icon--right"><ArrowRight /></el-icon>
            </el-button>
          </el-button-group> -->

          <el-breadcrumb separator="\">
            <template v-if="data.path">
              <el-breadcrumb-item
                v-for="(item, i) in data.path.split('\\').slice(0, -1)"
                :key="i"
                :to="{ path: '/' }"
                @click="onPathClick(i)"
              >
                <el-tooltip
                  class="box-item"
                  effect="dark"
                  :content="item"
                  placement="bottom"
                >
                  <div class="path">{{ item }}</div>
                </el-tooltip>
              </el-breadcrumb-item>
            </template>
          </el-breadcrumb>
          <div class="button-wrapper">
            <el-button-group>
              <el-button type="" size="small" @click="uploadDrawer.show = true">
                <i class="iconfont icon-cloud-upload"></i>
              </el-button>
              <el-button type="" size="small" @click="reloadDirectoryContents">
                <i class="iconfont icon-sync"></i>
              </el-button>
            </el-button-group>
          </div>
        </div>
        <el-scrollbar @contextmenu.prevent="openMenu($event)">
          <div class="dir-wrapper" v-if="data.fileInfos" style="height: 100%">
            <!-- <RecycleScroller
            class="scroller"
            :items="data.fileInfos"
            :item-size="64"
            :gridItems="10"
            key-field="physicalPath"
            v-slot="{ item }"
            style="height: 100%"
          > 
            <DirectoryContent
              :data="item"
              v-model:fileType="item.fileType"
              :key="item.physicalPath || ''"
              @onClick="onClickFile"
              @contextmenu.prevent.stop="openMenu($event, item)"
            >
            </DirectoryContent>
          </RecycleScroller> -->

            <el-space wrap>
              <DirectoryContent
                v-for="item in data.fileInfos"
                :data="item"
                v-model:fileType="item.fileType"
                :key="item.physicalPath || ''"
                @onClick="onClickFile"
                @contextmenu.prevent.stop="openMenu($event, item)"
              >
              </DirectoryContent>
            </el-space>
          </div>
        </el-scrollbar>
        <div class="footer-bar" v-if="data.fileInfos">
          <div class="">{{ data.fileInfos?.length }}个项目</div>
          <!-- <div class="button-wrapper">
            <el-button link @click="uploadDrawer.show = true"> 上传文件 </el-button>
          </div> -->
        </div>
        <!-- </el-scrollbar> -->
      </el-main>
    </el-container>
    <el-drawer v-model="fileDrawer.show" title="文件详情" direction="rtl" size="400px">
      <el-descriptions class="margin-top" :column="2" size="large" border>
        <el-descriptions-item :span="2" :min-width="90">
          <template #label>
            <div class="cell-item">文件名</div>
          </template>
          <div style="word-break: break-all">
            {{ fileDrawer.file.name }}
          </div>
        </el-descriptions-item>
        <el-descriptions-item :span="2" :min-width="90">
          <template #label>
            <div class="cell-item">物理路径</div>
          </template>
          <div style="word-break: break-all">
            {{ fileDrawer.file.physicalPath }}
          </div>
        </el-descriptions-item>
        <el-descriptions-item :span="2">
          <template #label>
            <div class="cell-item">文件大小</div>
          </template>
          {{ fileDrawer.fileSize }}
        </el-descriptions-item>
        <el-descriptions-item :span="2">
          <template #label>
            <div class="cell-item">修改时间</div>
          </template>
          {{ dayjs(fileDrawer.file.lastModified).format("YYYY/MM/DD HH:mm:ss") }}
        </el-descriptions-item>
      </el-descriptions>

      <div class="fileDrawer-button-wrapper">
        <el-button type="primary" @click="handleDownload">下载</el-button>
        <el-button
          style="margin-left: var(--el-drawer-padding-primary)"
          v-if="fileDrawer.file.fileType == 'VIDEO'"
          type="success"
          @click="handlePlayerVideo"
        >
          在线播放
        </el-button>
      </div>
    </el-drawer>
    <el-drawer
      v-model="uploadDrawer.show"
      title="文件上传"
      direction="rtl"
      size="400px"
      @closed="handleCloseUpload"
    >
      <el-upload
        class="upload-demo"
        ref="uploadRef"
        drag
        :action="`${domain}/NasFile/UploadFile`"
        :headers="headers"
        multiple
        :data="{ path: currentPath }"
        :on-success="
          () => {
            uploadDrawer.change = true;
            uploadRef.clearFiles();
          }
        "
        :on-error="onUploadError"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">拖放文件到此处或者 <em>点击上传</em></div>
        <!-- <template #tip>
          <div class="el-upload__tip">jpg/png files with a size less than 500kb</div>
        </template> -->
      </el-upload>
    </el-drawer>

    <transition name="fade-menu">
      <div
        v-show="rightMenu.show"
        :style="{ left: rightMenu.left + 'px', top: rightMenu.top + 'px' }"
        class="contextmenu"
      >
        <template v-if="rightMenu.file">
          <div @click="openFile">打开</div>
          <hr />
          <div @click="handleRenameDirectoryContents">重命名</div>
          <div @click="handleDeleteDirectoryContent">删除</div>
        </template>
        <div v-else @click="handleCreateDirectory">新建目录</div>
        <div @click="handleCopyPath">复制路径</div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import { useCommonStore } from "@/store/modules/common";
import DirectoryContent from "@/components/DirectoryContent.vue";
import nasFileService from "@/api-services/apis/nasFile";
import { ElNotification, ElMessageBox, ElMessage } from "element-plus";
import dayjs from "dayjs";
import { UploadFilled, Fold, Expand } from "@element-plus/icons-vue";
// import config from "@/config/config";
// import { RecycleScroller } from "vue-virtual-scroller";
// import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
import { isMobile } from "@/utils/common";
import bus from "vue3-eventbus";
import { GetAllDiskResult } from "@/api-services/models";
import {
  FileInfo,
  GetDirectoryContentsResultExt,
} from "@/api-services/models/extension/extension";
import storage from "@/utils/storage";
import useClipboard from "vue-clipboard3";
const domain = ref(
  import.meta.env.VITE_GLOB_SIGNALR_URL == "/"
    ? location.origin
    : import.meta.env.VITE_GLOB_SIGNALR_URL
);
const { toClipboard } = useClipboard();

const emits = defineEmits(["api"]);
const commonStore = useCommonStore();
const treeRef = ref<any>(null);
const finderRef = ref<any>(null);
const uploadRef = ref<any>(null);

const data = ref<GetDirectoryContentsResultExt>({});
//当前盘符集合
const diskList = ref<GetAllDiskResult[]>([]);
//当前目录树
const dirTree = ref<GetAllDiskResult[]>([]);
//当前树节点
const currentNode = ref<any>({});
//当前路径
const currentPath = ref("");
const miniLeft = ref(isMobile());
// const scrollTop = ref(0);

const accessToken = storage.getItem("access-token");
let head = {};
head["Authorization"] = `Bearer ${accessToken}`;
const headers = ref(head);
const fileDrawer = ref({
  show: false,
  file: <FileInfo>{},
  fileType: "",
  fileSize: "",
});
const uploadDrawer = ref({
  show: false,
  change: false, //有文件变动则为true
});

const rightMenu = ref({
  show: false,
  left: 0,
  top: 0,
  file: <FileInfo>{},
});

bus.on("uploadFile", () => {
  uploadDrawer.value.show = true;
});
bus.on("createFolder", () => {
  handleCreateDirectory();
});
bus.on("downloadTelegra", () => {
  handleDownloadTelegra();
});

function hideMenu() {
  rightMenu.value.show = false;
}

function openMenu(e, file?) {
  const menuMinWidth = 100;
  if (finderRef.value == null) return;
  const offsetLeft = finderRef.value.getBoundingClientRect().left; // container margin left
  const offsetTop = finderRef.value.getBoundingClientRect().top; // container margin left

  const offsetWidth = finderRef.value.offsetWidth; // container width
  const maxLeft = offsetWidth - menuMinWidth; // left boundary
  const left = e.clientX - offsetLeft; // margin right

  if (left > maxLeft) {
    rightMenu.value.left = maxLeft;
  } else {
    rightMenu.value.left = left;
  }

  rightMenu.value.top = e.clientY - offsetTop + 36;
  rightMenu.value.file = file;
  rightMenu.value.show = true;
}

/**
 * 重命名
 */
function handleRenameDirectoryContents() {
  // rightMenu.value.file.event = "rename";
  // nextTick(() => {
  //   rightMenu.value.file.event = ""; //清空事件名，方便下次触发
  // });
  console.log(rightMenu.value.file);
  ElMessageBox.prompt("请输入新名称", "重命名", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    inputPattern: /^((?!^ +| +$|:|<|>|\||\?|"|\/|\*|\\).)*$/,
    inputErrorMessage: "Invalid Email",
  })
    .then(async ({ value }) => {
      console.log(value);
      await nasFileService.RenameDirectoryContents({
        path: currentPath.value,
        oldName: rightMenu.value.file.name,
        newName: value,
        isDirectory: rightMenu.value.file.isDirectory,
      });
      ElNotification({
        title: "成功",
        message: "重命名成功",
        type: "success",
      });
      reloadDirectoryContents();
    })
    .catch(() => {});
}
/**
 * 新建目录
 */
function handleCreateDirectory() {
  ElMessageBox.prompt("请输入目录名称", "新建目录", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    inputPattern: /^((?!^ +| +$|:|<|>|\||\?|"|\/|\*|\\).)*$/, //前后不能有空格 不能有.
    inputErrorMessage: "非法名称",
  }).then(async ({ value }) => {
    let path = `${currentPath.value}${value}`;
    await nasFileService.CreateDirectory({ path });
    ElNotification({
      title: "成功",
      message: "目录已创建成功",
      type: "success",
    });
    handleGetDirectoryContents(path);
  });
}
/**
 * 删除目录或文件
 */
function handleDeleteDirectoryContent() {
  ElMessageBox.confirm(
    `确定要删除此${rightMenu.value.file.isDirectory ? "目录" : "文件"}?`,
    "删除确认",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
    .then(async () => {
      await nasFileService.DeleteDirectoryContent({
        path: rightMenu.value.file.physicalPath,
        isDirectory: rightMenu.value.file.isDirectory,
      });
      handleGetDirectoryContents(currentPath.value, true);
      ElNotification({
        title: "成功",
        message: `${rightMenu.value.file.isDirectory ? "目录" : "文件"}已删除`,
        type: "success",
      });
    })
    .catch(() => {});
}
async function handleGetAllDisk() {
  diskList.value = await nasFileService.GetAllDiskByUser();
  dirTree.value = diskList.value;
  handleGetDirectoryContents("");
}
handleGetAllDisk();

/**
 *
 * @param {*} path 相对路径
 */
async function handleGetDirectoryContents(path, reload?) {
  hideMenu();
  //如果有值 则\\结尾
  path = path ? `${path}${/\\$/.test(path) ? "" : "\\"}` : path;
  if (currentPath.value == path && !reload) return;
  emits("api", {
    event: "setWindowTitle",
    title: "加载中...",
  });
  commonStore.clearImages();
  currentPath.value = path;
  data.value = await nasFileService.GetDirectoryContents({
    path: path || diskList.value![0].path,
  });

  emits("api", {
    event: "setWindowTitle",
    title: path.split("\\").slice(-2)[0],
  });
}

function onClickFile(data) {
  // console.log(data);
  switch (data.fileType) {
    case "DIR":
      handleGetDirectoryContents(data.physicalPath);
      break;
    case "IMAGE":
      break;
    default:
      fileDrawer.value.file = data;
      // fileDrawer.value.fileType = data.fileType;
      fileDrawer.value.show = true;
      var size = (fileDrawer.value.file.length || 0) / 1024 / 1024; // MB

      fileDrawer.value.fileSize =
        size > 1024 ? `${(size / 1024).toFixed(2)} GB` : `${size.toFixed(2)} MB`;
      break;
  }
}

function openFile() {
  onClickFile(rightMenu.value.file);
}

/**
 * 点击面包屑路径
 * @param {*} i
 */
function onPathClick(i) {
  let path = "";
  if (!data.value || !data.value.path) return;
  var pathArray = data.value.path.split("\\").slice(0, i + 1);
  path = pathArray?.join("\\");
  handleGetDirectoryContents(path + "\\");
}

async function handleNodeClick(node) {
  currentNode.value = node;
  let path = node.physicalPath;
  await handleGetDirectoryContents(path);
  if (!data.value || !data.value.fileInfos) return;
  currentNode.value.children = data.value.fileInfos
    .filter((x) => x.isDirectory)
    .map((x) => {
      return {
        path: x.name,
        root: false,
        physicalPath: x.physicalPath,
      };
    });
}

async function handleDownload() {
  await nasFileService.FileDownload(
    fileDrawer.value.file.physicalPath,
    fileDrawer.value.file.name,
    true
  );
  // downloadFileByBlob(blob, fileDrawer.value.file.name);
}

async function handlePlayerVideo() {
  emits("api", {
    event: "openApp",
    app: "video_player",
    data: fileDrawer.value.file,
  });

  fileDrawer.value.show = false;
}

// function downloadFileByBlob(blob, fileName: string | null | undefined) {
//   let blobUrl = window.URL.createObjectURL(blob);
//   let link = document.createElement("a");
//   link.download = fileName || "defaultName";
//   link.style.display = "none";
//   link.href = blobUrl;
//   // 触发点击
//   document.body.appendChild(link);
//   link.click();
//   // 移除
//   document.body.removeChild(link);
// }

function handleCloseUpload() {
  if (uploadDrawer.value.change) {
    uploadRef.value.clearFiles();
    reloadDirectoryContents();
  }
}

function onUploadError(a) {
  console.log(a);
  // ElNotification({
  //   title: "上传失败",
  //   message: decodeURI(a.match(/(?<=").*?(?=")/)),
  //   type: "error",
  // });
}

async function reloadDirectoryContents() {
  await handleGetDirectoryContents(currentPath.value, true);
  ElMessage({
    message: "目录文件刷新成功",
    type: "success",
  });
}

function handleDownloadTelegra() {
  ElMessageBox.prompt("请输入电报图集地址", "下载套图", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    // inputPattern: /^((?!^ +| +$|\.|:|<|>|\||\?|"|\/|\*|\\).)*$/, //前后不能有空格 不能有.
    // inputErrorMessage: "非法名称",
  }).then(async ({ value }) => {
    // let path = `${currentPath.value}${value}`;
    nasFileService.DownloadTelegra({ path: currentPath.value, url: value });
    ElNotification({
      title: "成功",
      message: "任务已提交，请稍后再查看",
      type: "success",
    });
    reloadDirectoryContents();
  });
}

function handleCopyPath() {
  let path = rightMenu.value.file ? rightMenu.value.file.physicalPath : currentPath.value;
  if (path) {
    toClipboard(path);
    ElMessage({
      message: "路径已复制",
      type: "success",
    });
  }
}
</script>

<style scoped lang="scss">
.finder {
  --resize: 5px;
  --resize-bg: transparent;
  --resize-main: transparent;
  --resize-bg-main: transparent;
}

.finder-mobile {
  ::v-deep(.item) {
    width: 60px;
    .cover {
      width: 60px;
      height: 60px;
    }
    .title {
      font-size: 10px;
    }
    .image-placeholder {
      font-size: 10px;
    }
  }
}
.finder {
  display: flex;
  height: 100%;
  // min-height: 400px;
  width: 100%;
  color: #333;
  text-shadow: none;
  font-weight: 300;
  overflow: hidden;
  .list-left {
    // position: absolute;
    top: 40px;
    bottom: 0px;
    width: 200px;
    height: 100%;
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(20px);
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  ::v-deep(.el-space) {
    min-height: 0;
    overflow: hidden;
  }
  ::v-deep(.el-space__item) {
    min-height: 0;
    min-width: 0;
    overflow: hidden;
  }

  .list-right {
    flex: 1;
  }

  .left {
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(20px);
    display: flex;
    flex-direction: row;
    // justify-content: center;
    // align-items: center;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .left.miniLeft {
    width: 70px;

    .progress-wrapper,
    .title {
      display: none;
    }

    ::v-deep(.el-tree-node__children),
    ::v-deep(.el-tree-node__expand-icon) {
      display: none;
    }
    ::v-deep(.el-tree-node__content) {
      padding-left: 24px !important;
    }
  }

  .dir-tree {
    width: 100%;
    overflow: auto;

    ::v-deep(.el-tree-node__label) {
      padding-right: 24px;
      width: 100%;
    }
    ::v-deep(.el-tree-node__label) {
      font-size: var(--el-font-size-extra-small);
    }

    ::v-deep(.el-tree-node__content) {
      height: 40px;
    }

    ::v-deep(.el-tree-node__children .el-tree-node__content) {
      height: inherit !important;
    }
  }
  .tool-bar {
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(20px);
    display: flex;
    padding: 0px 0; //var(--el-main-padding);

    ::v-deep(.el-breadcrumb) {
      flex: 1;
      margin: 0 var(--el-main-padding);
      font-size: var(--el-font-size-extra-small);
    }
    ::v-deep(.el-breadcrumb__item) {
      height: 26px;
      line-height: 26px;
    }
    ::v-deep(.el-button) {
      // height: 26px;
      padding: 0 6px;
    }
    ::v-deep(.el-breadcrumb__separator) {
      margin: 0 1px;
    }

    .path {
      max-width: 60px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .button-wrapper {
      margin-right: 2px;
    }
  }
  .footer-bar {
    background: rgb(255 255 255 / 36%);
    // backdrop-filter: blur(20px);
    display: flex;
    padding: 0px var(--el-main-padding);
    font-size: var(--el-font-size-extra-small);

    height: 26px;
    line-height: 26px;
    .button-wrapper {
      flex: 1;
      text-align: right;
    }
  }

  .disk-wrapper {
    width: 100%;
    // .disk-icon {
    // }
    // .disk-icon-

    ::v-deep(.el-scrollbar) {
      height: calc(100% - 26px);
      width: 100% !important;
    }
    ::v-deep(.el-progress__text) {
      font-size: var(--el-font-size-extra-small) !important;
      text-align: right;
    }

    // .root {
    // }

    .disk-footer {
      height: 26px;
      line-height: 26px;
      display: flex;
      padding: 0px 20px;
      justify-content: center;
      align-items: center;

      .el-icon {
        color: #606266;
      }
    }
  }
  .folder-wrapper {
    padding: 0;

    ::v-deep(.el-scrollbar) {
      height: calc(100% - 26px - 26px);
      width: 100% !important;
    }

    .dir-wrapper {
      padding: var(--el-main-padding);
    }
  }
  ::v-deep(.el-drawer__body) {
    position: relative;
  }
  .fileDrawer-button-wrapper {
    display: flex;
    position: absolute;
    width: 100%;
    left: 0;
    padding: 0 20px;
    bottom: 20px;
    button:last-child {
      flex: 1;
      // margin-left: var(--el-drawer-padding-primary);
    }
  }
}

.contextmenu {
  position: absolute;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 5px;
  box-shadow: 0px 0px 10px rgb(0 0 0 / 30%);
  color: #333;
  font-size: 14px;
  text-align: left;
  width: 100px;
  overflow: hidden;
  padding: 2px 0px;
  text-shadow: none;
  z-index: 100;
  hr {
    border: none;
    border-top: 1px solid #ddd;
  }
  div {
    cursor: pointer;
    font-size: 13px !important;
    color: #333;
    border-radius: 5px;
    line-height: 2;
    padding: 0px 12px;
    display: flex;
    align-items: center;
    margin: 3px 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  div:hover {
    background: #4b9efb;
    color: white;
    border-radius: 5px;
  }
}

.scroller {
  height: 100%;
}
.user {
  height: 32%;
  padding: 0 12px;
  display: flex;
  align-items: center;
}
</style>
